Skip to content

Sync phase 1+2: upstream v0.9.29 bugfixes, env hydration, consolidation lifecycle, provider retry, unified data-dir - #7

Merged
ChronodeAi merged 8 commits into
mainfrom
sync/v0.9.29-phase2
Aug 24, 2026
Merged

Sync phase 1+2: upstream v0.9.29 bugfixes, env hydration, consolidation lifecycle, provider retry, unified data-dir#7
ChronodeAi merged 8 commits into
mainfrom
sync/v0.9.29-phase2

Conversation

@ChronodeAi

Copy link
Copy Markdown
Owner

Supersedes #6 (auto-closed when its stacked base branch merged and was deleted).

Contains the merged-and-green phase 1 train (#5: MEMORY.md path fix, honest memory_forget + lesson delete with tool inventory reconciled to 60, MCP protocolVersion negotiation) plus new phase 2 work:

  • Env hydration (6cc9b9f subset): fill-missing-only ~/.agentmemory/.env at boot; precedence real env > .env > project manifest > defaults; single parser shared with project-config
  • Provider retry: 429/503 honoring Retry-After under a 170s total budget (below iii's 180s), max 3 attempts
  • Consolidation on session stop: inside the existing background-pipeline keyed lock, only after persistPipelineSuccess; serialized cooldown marker (AGENTMEMORY_CONSOLIDATION_COOLDOWN_MS); stage-resume never re-runs completed stages; project-scoped payloads per fork scope policy
  • Unified data-dir resolver: --data-dir > AGENTMEMORY_DATA_DIR > ~/.agentmemory; upstream's silent cwd ./data adoption deliberately NOT ported (memory-poisoning vector) — warns and demands an explicit flag instead

Build hygiene: hook bundles regenerated; picocolors added to tsdown alwaysBundle after hydration made config.ts reachable from hook chunks (isolated-plugin-tree test caught it).

Test plan

  • vitest run: 1834/1835 (only failure is the pre-existing cli-connect repair case, fails identically on unmodified main)
  • tsc identical to baseline error set; R13 preflight passes; evidence:interfaces:test passes
  • Phase-1-only CI was green on all 4 platform/node matrices before this stack was added

Port the 6cc9b9f env-hydration subset. hydrateProcessEnvFromFile()
copies ~/.agentmemory/.env into process.env fill-missing-only, so a
real environment value always wins, and is wired before the first
config read in both entries (src/cli.ts after the --version/--help
exits, src/index.ts at the top of main()). loadEnvFile() is memoized
for the process lifetime with a __resetEnvFileCache() test hook.

loadAgentmemoryEnvironment() now delegates hydration to that single
implementation instead of re-parsing the file with dotenv, giving one
precedence story everywhere: real environment > ~/.agentmemory/.env >
project manifest overrides > defaults.
…psed budget

Port the 6cc9b9f _fetch.ts subset. fetchWithTimeout now retries
429/503 responses (max 3 total attempts) with the Retry-After delay —
integer-seconds or HTTP-date form, clamped to a 5s per-delay cap and
falling back to exponential backoff when absent. Retries are bounded by
the caller's TOTAL timeout budget, hard-capped at 170s so attempts +
sleeps can never approach the iii 180s invocation timeout; the first
attempt honors the capped budget too, and each late attempt gets only
the remaining time. Discarded response bodies are cancelled before
retrying so connections return to the pool.

Brings the bounded-retry regression cases from upstream's
test/fetch-timeout.test.ts: first-attempt cap, single retry, hostile /
oversized / HTTP-date Retry-After, small-budget bail-outs, and the
persistent-503 attempt cap.
…h a cooldown

Port the 6cc9b9f consolidation-lifecycle subset, reconciled with the
fork's persistent background-pipeline state. After the stop pipeline
reaches a successful terminal state — inside the existing
withKeyedLock('background-pipeline:'+sessionId) — the handler fires
mem::consolidate-pipeline {tier:'all',force:true} and
mem::auto-crystallize {olderThanDays:0}, both scoped to the session's
project (fork project-scope rules), gated on isConsolidationEnabled()
so keyless installs never fire no-op LLM work.

Debounce: a consolidation:lastRun marker in KV.config bounds corpus
consolidation to once per AGENTMEMORY_CONSOLIDATION_COOLDOWN_MS
(default 5 min, 0 disables). The read-check-write is serialized through
an in-process chain so concurrent stops cannot both pass. The gate sits
after every resume/supersede/terminal early-return, so retried runs
consume the cooldown only when they actually complete, stages the
resume machinery marks complete are never re-run, and failed pipelines
leave the marker untouched.

getConsolidationCooldownMs() added to config. New
test/consolidation-lifecycle.test.ts covers fire-once payloads, cooldown
suppression and expiry, debounce-disabled mode, stage-resume interplay,
failure paths not consuming the window, keyless gating, and concurrent
stop serialization; session-end-triggers-graph pins CONSOLIDATION_
ENABLED=false to keep its exact fan-out assertions hermetic.
…cy ./data warning

Port the d8b5267/e04ba88 core with fork semantics replacing upstream's:
src/data-dir.ts exports resolveDataDir() resolving --data-dir (separated
or = form) > AGENTMEMORY_DATA_DIR > ~/.agentmemory, with ~/ expansion
and cwd-relative resolution. Upstream's platform-default dirs and its
automatic adoption/copying of a legacy cwd ./data store are NOT ported;
instead, when no explicit data dir is configured and a ./data directory
holding an agentmemory store marker exists in cwd, boot logs a warning
pointing the operator at an explicit --data-dir.

config.ts drops the module-load DATA_DIR constant: the .env path,
loadConfig().dataDir, snapshot dir, and standalone persist path now
resolve lazily through the resolver; migrate.ts validates migration
dbPaths against allowedDirs() from it. cli.ts parses --data-dir before
anything reads the environment (folding the flag over any pre-set
AGENTMEMORY_DATA_DIR so flag > env holds for spawned processes), emits
the legacy-store warning once at boot, and documents the flag in --help.
Shared chunk hashes moved with the hydration/data-dir/retry changes;
CI rebuilds these committed outputs and a stale tree fails the R13
dirty-worktree check.
The hydration wiring made config.ts's provider hint reachable from the
_auth chunk, leaving an external picocolors import in committed bundles
and breaking the isolated-plugin-tree invariant. Bundle it like dotenv
and yaml so hooks stay dependency-free.
Phase 2's data-dir resolver added the env var without refreshing the
autogen environment block; skills:check drift gate caught it.
input_sha256 tracks the registered-function/route/env input set, which
the data-dir resolver and hydration wiring changed.
@ChronodeAi
ChronodeAi merged commit 11663f8 into main Aug 24, 2026
7 of 8 checks passed
@ChronodeAi
ChronodeAi deleted the sync/v0.9.29-phase2 branch August 24, 2026 18:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant